From 28f7888d7fc4aa75135ac1c566566eda1704db65 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 19 Mar 2007 16:48:24 +0000 Subject: [PATCH] hvm: Do not save/restore shared_info gpfn location. Instead of kludging a max_gpfn estimate in shared_info, add a new XENMEM command to discover the actual maximum gpfn value as known by the shadow code. This needs to be more robust when we support HVM ballooning in future anyway. One interesting point is that max_gpfn may be close to 4GB even for small-memory HVM guests since for example SVGA LFB is mapped into the I/O hole. We may need to special case the I/O hole somehow, or provide some finer-grained way to find out which parts of the GPFN space are actually used (e.g., get Xen to fill in a bitmap with 1 bit per 1024 pages, or similar). Signed-off-by: Keir Fraser --- tools/libxc/xc_core_x86.c | 24 +++++++++++------------- tools/libxc/xc_hvm_build.c | 1 - tools/libxc/xc_hvm_restore.c | 31 ------------------------------- tools/libxc/xc_hvm_save.c | 30 +----------------------------- tools/libxc/xc_private.c | 14 ++++++++++++++ xen/arch/x86/mm.c | 6 ++++++ xen/arch/x86/mm/shadow/common.c | 6 +++--- xen/common/compat/memory.c | 2 ++ xen/common/memory.c | 15 ++++++++++++++- xen/include/asm-ia64/mm.h | 2 ++ xen/include/asm-powerpc/mm.h | 2 ++ xen/include/asm-x86/mm.h | 1 + xen/include/public/memory.h | 5 +++++ 13 files changed, 61 insertions(+), 78 deletions(-) diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c index 6ea775aef6..bd82110713 100644 --- a/tools/libxc/xc_core_x86.c +++ b/tools/libxc/xc_core_x86.c @@ -21,12 +21,15 @@ #include "xg_private.h" #include "xc_core.h" +static int max_gpfn(int xc_handle, domid_t domid) +{ + return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid); +} + int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info) { - if ( info->hvm ) - return 1; - return 0; + return info->hvm; } int @@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { - unsigned long max_pfn = live_shinfo->arch.max_pfn; - xc_core_memory_map_t *map = NULL; + unsigned long max_pfn = max_gpfn(xc_handle, info->domid); + xc_core_memory_map_t *map; map = malloc(sizeof(*map)); - if ( !map ) + if ( map == NULL ) { PERROR("Could not allocate memory"); - goto out; + return -1; } map->addr = 0; @@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, *mapp = map; *nr_entries = 1; return 0; - -out: - if ( map ) - free(map); - return -1; } int @@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, xen_pfn_t *live_p2m_frame_list_list = NULL; xen_pfn_t *live_p2m_frame_list = NULL; uint32_t dom = info->domid; - unsigned long max_pfn = live_shinfo->arch.max_pfn; + unsigned long max_pfn = max_gpfn(xc_handle, info->domid); int ret = -1; int err; diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 4b23e9fdb1..751aa9cf7a 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -286,7 +286,6 @@ static int setup_guest(int xc_handle, /* NB. evtchn_upcall_mask is unused: leave as zero. */ memset(&shared_info->evtchn_mask[0], 0xff, sizeof(shared_info->evtchn_mask)); - shared_info->arch.max_pfn = page_array[nr_pages - 1]; munmap(shared_info, PAGE_SIZE); if ( v_end > HVM_BELOW_4G_RAM_END ) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 0dafa82874..4b54b0aaf5 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, { DECLARE_DOMCTL; - /* The new domain's shared-info frame number. */ - unsigned long shared_info_frame; - /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; @@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, uint8_t *hvm_buf = NULL; unsigned long long v_end, memsize; unsigned long shared_page_nr; - shared_info_t *shared_info = NULL; - xen_pfn_t arch_max_pfn; unsigned long pfn; unsigned int prev_pc, this_pc; @@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, /* Types of the pfns in the current region */ unsigned long region_pfn_type[MAX_BATCH_SIZE]; - struct xen_add_to_physmap xatp; - /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ unsigned long nr_pages; @@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, pfns[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ ) pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; - arch_max_pfn = pfns[max_pfn];/* used later */ /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( @@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, goto out; } - /* Shared-info pfn */ - if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { - ERROR("reading the shared-info pfn failed!\n"); - goto out; - } - /* Map the shared-info frame where it was before */ - xatp.domid = dom; - xatp.space = XENMAPSPACE_shared_info; - xatp.idx = 0; - xatp.gpfn = shared_info_frame; - if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) { - ERROR("setting the shared-info pfn failed!\n"); - goto out; - } - if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) || - ((shared_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - shared_info_frame)) == NULL) ) - goto out; - /* shared_info.arch.max_pfn is used by dump-core */ - shared_info->arch.max_pfn = arch_max_pfn; - munmap(shared_info, PAGE_SIZE); - rc = 0; goto out; diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index 54a3897ce5..75a017cf7c 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -302,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* The size of an array big enough to contain all guest pfns */ unsigned long pfn_array_size; - /* The new domain's shared-info frame number. */ - unsigned long shared_info_frame; - /* Other magic frames: ioreqs and xenstore comms */ unsigned long ioreq_pfn, bufioreq_pfn, store_pfn; @@ -318,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t hvm_buf_size; uint8_t *hvm_buf = NULL; - /* Live mapping of shared info structure */ - shared_info_t *live_shinfo = NULL; - /* base of the region in which domain memory is mapped */ unsigned char *region_base = NULL; @@ -372,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM:Could not get vcpu context"); goto out; } - shared_info_frame = info.shared_info_frame; /* cheesy sanity check */ if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { @@ -381,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* Map the shared info frame */ - if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, - PROT_READ, shared_info_frame))) { - ERROR("HVM:Couldn't map live_shinfo"); - goto out; - } - if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn) || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn) || xc_get_hvm_param(xc_handle, dom, @@ -525,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter); - if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) { - DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n", - max_pfn, live_shinfo->arch.max_pfn); - ERROR("Max pfn doesn't match shared info"); - goto out; - } - while( N < pfn_array_size ){ unsigned int this_pc = (N * 100) / pfn_array_size; @@ -679,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n", - info.shared_info_frame, + DPRINTF("SUSPEND eip %08lx edx %08lx\n", (unsigned long)ctxt.user_regs.eip, (unsigned long)ctxt.user_regs.edx); } @@ -768,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("write HVM info failed!\n"); } - /* Shared-info pfn */ - if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { - ERROR("write shared-info pfn failed!\n"); - goto out; - } - /* Success! */ rc = 0; diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 3816b0a83b..3e2557e581 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle, goto out1; } break; + case XENMEM_current_reservation: + case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: + if ( lock_pages(arg, sizeof(domid_t)) ) + { + PERROR("Could not lock"); + goto out1; + } + break; } ret = do_xen_hypercall(xc_handle, &hypercall); @@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle, case XENMEM_add_to_physmap: unlock_pages(arg, sizeof(struct xen_add_to_physmap)); break; + case XENMEM_current_reservation: + case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: + unlock_pages(arg, sizeof(domid_t)); + break; } out1: diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1c65070d15..e0590f33a2 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -108,6 +108,7 @@ #include #include #include +#include #include #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a) @@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p) return 0; } +unsigned long domain_get_maximum_gpfn(struct domain *d) +{ + return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d); +} + void share_xen_page_with_guest( struct page_info *page, struct domain *d, int readonly) { diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 15ebf1d541..efabba8223 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "private.h" @@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain *d) { ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL); d->arch.paging.shadow.dirty_bitmap_size = - (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) & + (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); d->arch.paging.shadow.dirty_bitmap = xmalloc_array(unsigned long, @@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain *d) d->arch.paging.shadow.dirty_bitmap_size = 0; return -ENOMEM; } - memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8); + memset(d->arch.paging.shadow.dirty_bitmap, 0, + d->arch.paging.shadow.dirty_bitmap_size/8); return 0; } diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c index 1301e42f04..53628d7a35 100644 --- a/xen/common/compat/memory.c +++ b/xen/common/compat/memory.c @@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat) case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: { #define xen_domid_t domid_t #define compat_domid_t domid_compat_t @@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat) case XENMEM_maximum_ram_page: case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: break; case XENMEM_translate_gpfn_list: diff --git a/xen/common/memory.c b/xen/common/memory.c index f7e5efc0a5..edd2ebe8d5 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: if ( copy_from_guest(&domid, arg, 1) ) return -EFAULT; @@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) else if ( (d = rcu_lock_domain_by_id(domid)) == NULL ) return -ESRCH; - rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages; + switch ( op ) + { + case XENMEM_current_reservation: + rc = d->tot_pages; + break; + case XENMEM_maximum_reservation: + rc = d->max_pages; + break; + default: + ASSERT(op == XENMEM_maximum_gpfn); + rc = domain_get_maximum_gpfn(d); + break; + } if ( unlikely(domid != DOMID_SELF) ) rcu_unlock_domain(d); diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index fa0830d414..057f841c16 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -511,4 +511,6 @@ int steal_page( #define domain_clamp_alloc_bitsize(d, b) (b) +#define domain_get_maximum_gpfn(d) (-ENOSYS) + #endif /* __ASM_IA64_MM_H__ */ diff --git a/xen/include/asm-powerpc/mm.h b/xen/include/asm-powerpc/mm.h index e258d5eb1b..ed6a10c67b 100644 --- a/xen/include/asm-powerpc/mm.h +++ b/xen/include/asm-powerpc/mm.h @@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, struct page_info *page, #define domain_clamp_alloc_bitsize(d, b) (b) +#define domain_get_maximum_gpfn(d) (-ENOSYS) + #endif diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index b240e4b5ca..225605efd4 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits); # define domain_clamp_alloc_bitsize(d, b) (b) #endif +unsigned long domain_get_maximum_gpfn(struct domain *d); #endif /* __ASM_X86_MM_H__ */ diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 97a6bbfea2..7b1ef44d32 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -128,6 +128,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); #define XENMEM_current_reservation 3 #define XENMEM_maximum_reservation 4 +/* + * Returns the maximum GPFN in use by the guest, or -ve errcode on failure. + */ +#define XENMEM_maximum_gpfn 14 + /* * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys * mapping table. Architectures which do not have a m2p table do not implement -- 2.30.2